Search Results for

    Show / Hide Table of Contents

    The Custom Free Surface 3D Chart Type

    In SciChart, Custom Free Surface 3D Charts are provided by the combination of the Free Surface 3D Series and CustomSurfaceDataSeries3D<TX,TY,TZ> underlying DataSeries.

    The location of the CustomSurfaceDataSeries3D<TX,TY,TZ> is defined by following properties:

    • offsetX – a location of the Custom Free Surface by the X-Axis;
    • offsetY – a location of the Custom Free Surface by the Y-Axis;
    • offsetZ – a location of the Custom Free Surface by the Z-Axis;

    The shape of its surface is defined by a set of user-defined functions, injected in the Constructor during the instantiation. This approach allows the surface to obtain any possible shape.

    Some of the CustomSurfaceDataSeries3D<TX,TY,TZ> Constructor are described below:

    • Radial Distance Function – function that determines how distance from the origin to the particular point on the surface differs.
    • Azimuthal Angle Function – function that determines the azimuthal angle between the particular point and the unit vector of the X-Axis, projected on the XZ plane.
    • Polar Angle Function – is a user-defined function that determines inclination (or polar angle) between the particular point and the unit vector of the Y-Axis - Zenith.
    Note

    The U and V coordinates in intervals [uMin...uMax] and [vMin...vMax] respectively are passed as the arguments to each of the three functions above.

    • X Function - function that determines the position of the particular point on the surface by the X-Axis.
    • Y Function - function that determines the position of the particular point on the surface by the Y-Axis.
    • Z Function - function that determines the position of the particular point on the surface by the Z-Axis.
    Note

    The Radial Distance, Radial Distance and Azimuthal Angle are passed as the arguments to each of the three functions above. More information about the radial distance, azimuthal and polar angle can be found here: Spherical coordinate system.

    Custom Free Surface Chart 3D

    Note

    Examples for the Custom Free Surface 3D can be found in the SciChart Android Examples Suite as well as on GitHub:

    • Native Example
    • Xamarin Example

    Let's see some examples of declaring some 3D Free Surfaces:

    • Custom Free Surface 3D
    • Simple Sphere
    • Simple Cylinder

    Create a Custom Free Surface 3D Chart

    To create a Custom Free Surface 3D Chart like the above - use the following code:

    • Java
    • Java with Builders API
    • Kotlin
    final CustomSurfaceDataSeries3D.UVFunc radialDistanceFunc = (u, v) -> 5d + Math.sin(5 * (u + v));
    final CustomSurfaceDataSeries3D.UVFunc azimuthalAngleFunc = (u, v) -> u;
    final CustomSurfaceDataSeries3D.UVFunc polarAngleFunc = (u, v) -> v;
    
    final CustomSurfaceDataSeries3D.ValueFunc<Double> xFunc = (r, theta, phi) -> r * Math.sin(theta) * Math.cos(phi);
    final CustomSurfaceDataSeries3D.ValueFunc<Double> yFunc = (r, theta, phi) -> r * Math.cos(theta);
    final CustomSurfaceDataSeries3D.ValueFunc<Double> zFunc = (r, theta, phi) -> r * Math.sin(theta) * Math.sin(phi);
    
    final CustomSurfaceDataSeries3D<Double, Double, Double> ds = new CustomSurfaceDataSeries3D<>(Double.class, Double.class, Double.class,
            30, 30,
            radialDistanceFunc, azimuthalAngleFunc, polarAngleFunc,
            xFunc, yFunc, zFunc,
            0d, Math.PI * 2, 0, Math.PI
    );
    
    int[] colors = new int[]{0xFF1D2C6B, Blue, Cyan, GreenYellow, Yellow, Red, DarkRed};
    float[] stops = new float[]{0, .1f, .3f, .5f, .7f, .9f, 1};
    final GradientColorPalette palette = new GradientColorPalette(colors, stops);
    
    final FreeSurfaceRenderableSeries3D rs = new FreeSurfaceRenderableSeries3D();
    rs.setDataSeries(ds);
    rs.setDrawMeshAs(DrawMeshAs.SolidWireframe);
    rs.setStroke(0x77228B22);
    rs.setContourInterval(0.1f);
    rs.setContourStroke(0x77228B22);
    rs.setStrokeThickness(convertValueToDp(2f));
    rs.setLightingFactor(0.8f);
    rs.setMeshColorPalette(palette);
    rs.setPaletteMinMaxMode(FreeSurfacePaletteMinMaxMode.Relative);
    rs.setPaletteMinimum(new Vector3(0f, 5f, 0f));
    rs.setPaletteMaximum(new Vector3(0f, 7f, 0f));
    
    final CustomSurfaceDataSeries3D.UVFunc radialDistanceFunc = (u, v) -> 5d + Math.sin(5 * (u + v));
    final CustomSurfaceDataSeries3D.UVFunc azimuthalAngleFunc = (u, v) -> u;
    final CustomSurfaceDataSeries3D.UVFunc polarAngleFunc = (u, v) -> v;
    
    final CustomSurfaceDataSeries3D.ValueFunc<Double> xFunc = (r, theta, phi) -> r * Math.sin(theta) * Math.cos(phi);
    final CustomSurfaceDataSeries3D.ValueFunc<Double> yFunc = (r, theta, phi) -> r * Math.cos(theta);
    final CustomSurfaceDataSeries3D.ValueFunc<Double> zFunc = (r, theta, phi) -> r * Math.sin(theta) * Math.sin(phi);
    
    final CustomSurfaceDataSeries3D<Double, Double, Double> ds = new CustomSurfaceDataSeries3D<>(Double.class, Double.class, Double.class,
            30, 30,
            radialDistanceFunc, azimuthalAngleFunc, polarAngleFunc,
            xFunc, yFunc, zFunc,
            0d, Math.PI * 2, 0, Math.PI
    );
    
    int[] colors = new int[]{0xFF1D2C6B, Blue, Cyan, GreenYellow, Yellow, Red, DarkRed};
    float[] stops = new float[]{0, .1f, .3f, .5f, .7f, .9f, 1};
    final GradientColorPalette palette = new GradientColorPalette(colors, stops);
    
    final FreeSurfaceRenderableSeries3D rs = sciChart3DBuilder.newFreeSurfaceSeries3D()
            .withDataSeries(ds)
            .withDrawMeshAs(DrawMeshAs.SolidWireframe)
            .withStroke(0x77228B22)
            .withContourInterval(0.1f)
            .withContourStroke(0x77228B22)
            .withStrokeThicknes(2f)
            .withLightingFactor(0.8f)
            .withMeshColorPalette(palette)
            .withPaletteMinMaxMode(FreeSurfacePaletteMinMaxMode.Relative)
            .withPaletteMinimum(new Vector3(0f, 5f, 0f))
            .withPaletteMaximum(new Vector3(0f, 7f, 0f))
            .build();
    
    val radialDistanceFunc = UVFunc { u: Double, v: Double -> 5.0 + Math.sin(5 * (u + v)) }
    val azimuthalAngleFunc = UVFunc { u: Double, v: Double -> u }
    val polarAngleFunc = UVFunc { u: Double, v: Double -> v }
    
    val xFunc = ValueFunc { r: Double, theta: Double, phi: Double -> r * Math.sin(theta) * Math.cos(phi) }
    val yFunc = ValueFunc { r: Double, theta: Double, phi: Double -> r * Math.cos(theta) }
    val zFunc = ValueFunc { r: Double, theta: Double, phi: Double -> r * Math.sin(theta) * Math.sin(phi) }
    
    val ds = CustomSurfaceDataSeries3D(
        Double::class.java, Double::class.java, Double::class.java,
        30, 30,
        radialDistanceFunc, azimuthalAngleFunc, polarAngleFunc,
        xFunc, yFunc, zFunc,
        0.0, Math.PI * 2, 0.0, Math.PI
    )
    
    val colors = intArrayOf(0xFF1D2C6B.toInt(), ColorUtil.Blue, ColorUtil.Cyan, ColorUtil.GreenYellow, ColorUtil.Yellow, ColorUtil.Red, ColorUtil.DarkRed)
    val stops = floatArrayOf(0f, .1f, .3f, .5f, .7f, .9f, 1f)
    val palette = GradientColorPalette(colors, stops)
    
    val rs = FreeSurfaceRenderableSeries3D()
    rs.dataSeries = ds
    rs.drawMeshAs = DrawMeshAs.SolidWireframe
    rs.stroke = 0x77228B22
    rs.contourInterval = 0.1f
    rs.contourStroke = 0x77228B22
    rs.strokeThickness = convertValueToDp(2f)
    rs.lightingFactor = 0.8f
    rs.meshColorPalette = palette
    rs.paletteMinMaxMode = FreeSurfacePaletteMinMaxMode.Relative
    rs.paletteMinimum = Vector3(0f, 5f, 0f)
    rs.paletteMaximum = Vector3(0f, 7f, 0f)
    
    Note

    See other constrained and unconstrained Free Surface Series types in the corresponding articles.

    Create a Simple Sphere

    Let's create a simple Sphere with a Radius = 10. See the user-defined functions which is used in the CustomSurfaceDataSeries3D<TX,TY,TZ> in the code below:

    • Java
    • Java with Builders API
    • Kotlin
    final CustomSurfaceDataSeries3D.UVFunc radialDistanceFunc = (u, v) -> 10;
    final CustomSurfaceDataSeries3D.UVFunc azimuthalAngleFunc = (u, v) -> u;
    final CustomSurfaceDataSeries3D.UVFunc polarAngleFunc = (u, v) -> v;
    
    final CustomSurfaceDataSeries3D.ValueFunc<Double> xFunc = (r, theta, phi) -> r * Math.sin(theta) * Math.cos(phi);
    final CustomSurfaceDataSeries3D.ValueFunc<Double> yFunc = (r, theta, phi) -> r * Math.cos(theta);
    final CustomSurfaceDataSeries3D.ValueFunc<Double> zFunc = (r, theta, phi) -> r * Math.sin(theta) * Math.sin(phi);
    
    final CustomSurfaceDataSeries3D<Double, Double, Double> ds = new CustomSurfaceDataSeries3D<>(Double.class, Double.class, Double.class,
            30, 30,
            radialDistanceFunc, azimuthalAngleFunc, polarAngleFunc,
            xFunc, yFunc, zFunc,
            0d, Math.PI * 2, 0, Math.PI
    );
    
    final CustomSurfaceDataSeries3D.UVFunc radialDistanceFunc = (u, v) -> 5d + Math.sin(5 * (u + v));
    final CustomSurfaceDataSeries3D.UVFunc azimuthalAngleFunc = (u, v) -> u;
    final CustomSurfaceDataSeries3D.UVFunc polarAngleFunc = (u, v) -> v;
    
    final CustomSurfaceDataSeries3D.ValueFunc<Double> xFunc = (r, theta, phi) -> r * Math.sin(theta) * Math.cos(phi);
    final CustomSurfaceDataSeries3D.ValueFunc<Double> yFunc = (r, theta, phi) -> r * Math.cos(theta);
    final CustomSurfaceDataSeries3D.ValueFunc<Double> zFunc = (r, theta, phi) -> r * Math.sin(theta) * Math.sin(phi);
    
    final CustomSurfaceDataSeries3D<Double, Double, Double> ds = new CustomSurfaceDataSeries3D<>(Double.class, Double.class, Double.class,
            30, 30,
            radialDistanceFunc, azimuthalAngleFunc, polarAngleFunc,
            xFunc, yFunc, zFunc,
            0d, Math.PI * 2, 0, Math.PI
    );
    
    val radialDistanceFunc = UVFunc { u: Double, v: Double -> 5.0 + Math.sin(5 * (u + v)) }
    val azimuthalAngleFunc = UVFunc { u: Double, v: Double -> u }
    val polarAngleFunc = UVFunc { u: Double, v: Double -> v }
    
    val xFunc = ValueFunc { r: Double, theta: Double, phi: Double -> r * Math.sin(theta) * Math.cos(phi) }
    val yFunc = ValueFunc { r: Double, theta: Double, phi: Double -> r * Math.cos(theta) }
    val zFunc = ValueFunc { r: Double, theta: Double, phi: Double -> r * Math.sin(theta) * Math.sin(phi) }
    
    val ds = CustomSurfaceDataSeries3D(
        Double::class.java, Double::class.java, Double::class.java,
        30, 30,
        radialDistanceFunc, azimuthalAngleFunc, polarAngleFunc,
        xFunc, yFunc, zFunc,
        0.0, Math.PI * 2, 0.0, Math.PI
    )
    

    Simple Sphere 3D

    Create a Simple Cylinder

    Let's create a simple Cylinder with a Radius = 10 and Height = 40. See the code below:

    • Java
    • Java with Builders API
    • Kotlin
    final CustomSurfaceDataSeries3D.UVFunc radialDistanceFunc = (u, v) -> 0.0;
    final CustomSurfaceDataSeries3D.UVFunc azimuthalAngleFunc = (u, v) -> u;
    final CustomSurfaceDataSeries3D.UVFunc polarAngleFunc = (u, v) -> v;
    
    final CustomSurfaceDataSeries3D.ValueFunc<Double> xFunc = (r, theta, phi) -> 10 * Math.sin(Math.PI / 2) * Math.cos(phi);
    final CustomSurfaceDataSeries3D.ValueFunc<Double> yFunc = (r, theta, phi) -> 40 * Math.cos(theta);
    final CustomSurfaceDataSeries3D.ValueFunc<Double> zFunc = (r, theta, phi) -> 10 * Math.sin(Math.PI / 2) * Math.sin(phi);
    
    final CustomSurfaceDataSeries3D<Double, Double, Double> ds = new CustomSurfaceDataSeries3D<>(Double.class, Double.class, Double.class,
            30, 30,
            radialDistanceFunc, azimuthalAngleFunc, polarAngleFunc,
            xFunc, yFunc, zFunc,
            0d, Math.PI * 2, 0, Math.PI
    );
    
    final CustomSurfaceDataSeries3D.UVFunc radialDistanceFunc = (u, v) -> 0.0;
    final CustomSurfaceDataSeries3D.UVFunc azimuthalAngleFunc = (u, v) -> u;
    final CustomSurfaceDataSeries3D.UVFunc polarAngleFunc = (u, v) -> v;
    
    final CustomSurfaceDataSeries3D.ValueFunc<Double> xFunc = (r, theta, phi) -> 10 * Math.sin(Math.PI / 2) * Math.cos(phi);
    final CustomSurfaceDataSeries3D.ValueFunc<Double> yFunc = (r, theta, phi) -> 40 * Math.cos(theta);
    final CustomSurfaceDataSeries3D.ValueFunc<Double> zFunc = (r, theta, phi) -> 10 * Math.sin(Math.PI / 2) * Math.sin(phi);
    
    final CustomSurfaceDataSeries3D<Double, Double, Double> ds = new CustomSurfaceDataSeries3D<>(Double.class, Double.class, Double.class,
            30, 30,
            radialDistanceFunc, azimuthalAngleFunc, polarAngleFunc,
            xFunc, yFunc, zFunc,
            0d, Math.PI * 2, 0, Math.PI
    );
    
    val radialDistanceFunc = UVFunc { u: Double, v: Double -> 0.0 }
    val azimuthalAngleFunc = UVFunc { u: Double, v: Double -> u }
    val polarAngleFunc = UVFunc { u: Double, v: Double -> v }
    
    val xFunc = ValueFunc { r: Double, theta: Double, phi: Double -> 10 * Math.sin(Math.PI / 2) * Math.cos(phi) }
    val yFunc = ValueFunc { r: Double, theta: Double, phi: Double -> 40 * Math.cos(theta) }
    val zFunc = ValueFunc { r: Double, theta: Double, phi: Double -> 10 * Math.sin(Math.PI / 2) * Math.sin(phi) }
    
    val ds = CustomSurfaceDataSeries3D(
        Double::class.java, Double::class.java, Double::class.java,
        30, 30,
        radialDistanceFunc, azimuthalAngleFunc, polarAngleFunc,
        xFunc, yFunc, zFunc,
        0.0, Math.PI * 2, 0.0, Math.PI
    )
    

    Simple Cylinder 3D

    Back to top © 2011-2025 SciChart. All rights reserved. | sitemap.xml